package com.xxwy.ddu.cms.authonrize.service.impl;


import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.xxwy.ddu.cms.authonrize.entity.BaseUser;
import com.xxwy.ddu.cms.authonrize.entity.Role;
import com.xxwy.ddu.cms.authonrize.entity.UserRoles;
import com.xxwy.ddu.cms.authonrize.mapper.RoleMapper;
import com.xxwy.ddu.cms.authonrize.mapper.UserMapper;
import com.xxwy.ddu.cms.authonrize.mapper.UserRolesMapper;
import com.xxwy.ddu.cms.authonrize.service.IUserService;
import com.xxwy.ddu.common.exception.IllegalParameterException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xxwy
 * @since 2018-08-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, BaseUser> implements IUserService, UserDetailsService, SocialUserDetailsService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder encoder;


    @Override
    public Page<BaseUser> selectUserWithRole(Page<BaseUser> page) {
        List<BaseUser> baseUsers = userMapper.selectUserWithRole(page);
        page.setRecords(baseUsers);
        page.setTotal(baseUsers.size());
        return page;
    }

    @Transactional
    @Override
    public void insertUserWithRole(BaseUser baseUser) {
        BaseUser select = new BaseUser();
        select.setuName(baseUser.getuName());
        BaseUser selectOne = userMapper.selectOne(baseUser);
        if (selectOne != null) {
            throw new IllegalParameterException("用户已存在");
        }
        baseUser.setuPassword(encoder.encode(baseUser.getuPassword()));
        baseUser.setBlock(false);
        baseUser.setDeleteFlag(0);
        baseUser.setuCreatetime(new Date());
        userMapper.insert(baseUser);
        //查出用户id
        select = userMapper.selectOne(select);
        Integer u_id = select.getuId();
        for (Role role : baseUser.getRoles()) {
            UserRoles build = UserRoles.builder().uId(u_id).rId(role.getrId()).deleteFlag(0).build();
            build.insert();
        }
    }

    @Override
    public BaseUser selectUserByName(String uname) {
        BaseUser select = userMapper.selectByNameWithRole(uname);
        return select;
    }

    /**
     * 默认的处理登录的请求
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //传入的值username / phone , 存储的时候判断用户名不能是纯数组
        boolean mobile = isMobile(username);
        if (mobile) {
            BaseUser baseUser = userMapper.selectByNameWithPhone(username);
            if (baseUser == null) {
                throw new UsernameNotFoundException("该用户不存在");
            }
            Bingding bingding = new Bingding(baseUser).invoke();
            ArrayList<SimpleGrantedAuthority> authorities = bingding.getAuthorities();
            boolean isDeleteFlag = bingding.isDeleteFlag();
            return new User(baseUser.getuName(), baseUser.getuPassword(),
                    isDeleteFlag, true, true, !baseUser.getBlock(), authorities);

        } else {
            BaseUser baseUser = userMapper.selectByNameWithRole(username);
            if (baseUser == null) {
                throw new UsernameNotFoundException("该用户不存在");
            }
            Bingding bingding = new Bingding(baseUser).invoke();
            ArrayList<SimpleGrantedAuthority> authorities = bingding.getAuthorities();
            boolean isDeleteFlag = bingding.isDeleteFlag();
            return new User(baseUser.getuName(), baseUser.getuPassword(),
                    isDeleteFlag, true, true, !baseUser.getBlock(), authorities);
        }
    }

    private boolean isMobile(String str) {
        Pattern p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); // 验证手机号
        Matcher m = p.matcher(str);
        boolean b = m.matches();
        return b;
    }


    /**
     * 社交登录时用的
     *
     * @param userId
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
        BaseUser baseUser = userMapper.selectById(userId);
        if (baseUser == null) {
            throw new UsernameNotFoundException("该用户不存在");
        }
        Bingding bingding = new Bingding(baseUser).invoke();
        ArrayList<SimpleGrantedAuthority> authorities = bingding.getAuthorities();
        boolean isDeleteFlag = bingding.isDeleteFlag();
        return new SocialUser(baseUser.getuName(), baseUser.getuPassword(),
                isDeleteFlag, true, true, !baseUser.getBlock(), authorities);
    }


    private class Bingding {
        private BaseUser baseUser;
        private ArrayList<SimpleGrantedAuthority> authorities;
        private boolean isDeleteFlag;

        public Bingding(BaseUser baseUser) {
            this.baseUser = baseUser;
        }

        public ArrayList<SimpleGrantedAuthority> getAuthorities() {
            return authorities;
        }

        public boolean isDeleteFlag() {
            return isDeleteFlag;
        }

        public Bingding invoke() {
            authorities = new ArrayList<>();
            if (baseUser.getRoles() != null && !baseUser.getRoles().isEmpty()) {
                baseUser.getRoles().stream().forEach((x) -> {
                    authorities.add(new SimpleGrantedAuthority(x.getrName()));
                });
            }
            isDeleteFlag = true;
            if (baseUser.getDeleteFlag() == 1) {
                isDeleteFlag = false;
            }
            return this;
        }
    }
}
